package com.nuoniu.sibanyun.service.expenses.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.entity.crm.CrmGoodsOrder;
import com.nuoniu.sibanyun.entity.crm.call.CrmCallMinutes;
import com.nuoniu.sibanyun.entity.expenses.ExpensesAccount;
import com.nuoniu.sibanyun.entity.expenses.ExpensesBalanceChangeRecord;
import com.nuoniu.sibanyun.entity.expenses.ExpensesBusinessOrder;
import com.nuoniu.sibanyun.entity.expenses.ExpensesPaymentOrder;
import com.nuoniu.sibanyun.entity.expenses.dto.ExpensesAccountSearchDto;
import com.nuoniu.sibanyun.mapper.expenses.ExpensesAccountMapper;
import com.nuoniu.sibanyun.service.crm.call.ICrmCallMinutesService;
import com.nuoniu.sibanyun.service.expenses.IExpensesAccountService;
import com.nuoniu.sibanyun.service.expenses.IExpensesBalanceChangeRecordService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * <p>
 * 费用中心-账户管理 服务实现类
 * </p>
 *
 * @author 白强
 * @since 2022-05-06
 */
@Service
@Log4j2
public class ExpensesAccountServiceImpl extends ServiceImpl<ExpensesAccountMapper, ExpensesAccount> implements IExpensesAccountService {

    @Autowired
    private IExpensesBalanceChangeRecordService changeRecordService;
    @Autowired
    @Lazy
    private ICrmCallMinutesService crmCallMinutesService;

    @Override
    public void initExpensesAccount(Integer companyId) {
        ExpensesAccount account = this.getByCompany(companyId);
        if(null != account) {
            return;
        }
        account = new ExpensesAccount();
        account.setCompanyId(companyId);
        account.setBalance(new BigDecimal(0));
        save(account);
    }

    @Override
    public ExpensesAccount getByCompany(Integer companyId) {
        QueryWrapper<ExpensesAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id",companyId);
        queryWrapper.last("LIMIT 1");
        ExpensesAccount account = getOne(queryWrapper);
        return account;
    }

    @Override
    public Page<ExpensesAccount> pageList(ExpensesAccountSearchDto accountSearchDto) {
        Integer companyId = accountSearchDto.getCompanyId();
        QueryWrapper<ExpensesAccount> queryWrapper = new QueryWrapper<>();
        if(null != companyId){
            queryWrapper.eq("company_id",companyId);
        }
        queryWrapper.orderByDesc("balance");
        Page page = page(accountSearchDto.getPage(), queryWrapper);
        return page;
    }
    /**
     * 处理业务订单
     * @param businessOrder
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void changeFromBusinessOrder(ExpensesBusinessOrder businessOrder) {
        Integer orderStatus = businessOrder.getStatus();
        BigDecimal orderAmount = businessOrder.getOrderAmount();
        if(!orderStatus.equals(3) || orderAmount.compareTo(BigDecimal.ZERO) == 0) {
            return;
        }
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        ExpensesAccount account = getByCompany(companyId);
        BigDecimal balance = account.getBalance();
        if(balance.compareTo(orderAmount) < 0) {
            throw new NuoNiuException("余额不足，请先充值");
        }
        /** 1.新增收支明细*/
        ExpensesBalanceChangeRecord changeRecord = new ExpensesBalanceChangeRecord();
        changeRecord.setTransactionType("Deduction");
        changeRecord.setTransactionChannel("Balance");
        changeRecord.setSourceOrderNo(businessOrder.getBusinessOrderNo());
        changeRecord.setOutAmount(businessOrder.getOrderAmount());
        BigDecimal beforeChangeBalance = balance;
        BigDecimal afterChangeBalance = beforeChangeBalance.subtract(orderAmount);
        changeRecord.setBeforeChangeBalance(beforeChangeBalance);
        changeRecord.setAfterChangeBalance(afterChangeBalance);
        changeRecord.setTransactionTime(LocalDateTime.now());
        changeRecordService.addRecord(changeRecord);
        /** 2.更新余额 */
        account.setBalance(afterChangeBalance);
        this.updateById(account);
    }

    @Override
    public void changeFromCrmGoodsOrder(CrmGoodsOrder crmGoodsOrder) {
        Integer orderStatus = crmGoodsOrder.getOrderStatus();
        BigDecimal orderAmount = crmGoodsOrder.getSalePrice();
        if(!orderStatus.equals(1) || orderAmount.compareTo(BigDecimal.ZERO) == 0) {
            return;
        }
        Integer companyId = crmGoodsOrder.getCompanyId();
        ExpensesAccount account = getByCompany(companyId);
        BigDecimal balance = account.getBalance();
        BigDecimal deposit = account.getDeposit();
        if(balance.compareTo(orderAmount) < 0) {
            throw new NuoNiuException("余额不足，请先充值");
        }
        /** 1.新增收支明细*/
        ExpensesBalanceChangeRecord changeRecord = new ExpensesBalanceChangeRecord();
        /** 订单业务类型 商品订单：Goods 购买通用分钟数：GeneralMinutes 保证金充值:Deposit  保证金扣费 DeDeposit*/
        String orderBusinessType = crmGoodsOrder.getOrderBusinessType();
        String transactionType = "Deduction";
        String transactionChannel = "Balance";
        switch (orderBusinessType){
//            /** 购买保证金 */
//            case "Deposit":
//                transactionType = "Deposit";
//                /** 减少 可用余额*/
//                BigDecimal beforeChangeBalance = balance;
//                BigDecimal afterChangeBalance = beforeChangeBalance.subtract(orderAmount);
//                changeRecord.setBeforeChangeBalance(beforeChangeBalance);
//                changeRecord.setAfterChangeBalance(afterChangeBalance);
//                account.setBalance(afterChangeBalance);
//                /** 增加 保证金*/
//                BigDecimal beforeChangeDeposit = deposit;
//                BigDecimal afterChangeDeposit = beforeChangeDeposit.add(orderAmount);
//                changeRecord.setBeforeChangeDeposit(beforeChangeDeposit);
//                changeRecord.setAfterChangeDeposit(afterChangeDeposit);
//                account.setDeposit(afterChangeDeposit);
//
//                break;
//            /** 使用 保证金 */
//            case "DeDeposit":
//                transactionType = "DeDeposit";
//                transactionChannel = "Deposit";
//                if(deposit.compareTo(orderAmount) < 0)throw new NuoNiuException("保证金不足，请先充值保证金");
//                BigDecimal beforeChangeDeposit1 = deposit;
//                BigDecimal afterChangeDeposit1 = beforeChangeDeposit1.subtract(orderAmount);
//                changeRecord.setBeforeChangeDeposit(beforeChangeDeposit1);
//                changeRecord.setAfterChangeDeposit(afterChangeDeposit1);
//                account.setDeposit(afterChangeDeposit1);
//                break;
            /** 使用 可用余额 */
            default:
                BigDecimal beforeChangeBalance1 = balance;
                BigDecimal afterChangeBalance1 = beforeChangeBalance1.subtract(orderAmount);
                changeRecord.setBeforeChangeBalance(beforeChangeBalance1);
                changeRecord.setAfterChangeBalance(afterChangeBalance1);
                account.setBalance(afterChangeBalance1);
                break;

        }
        changeRecord.setCompanyId(companyId);
        changeRecord.setTransactionType(transactionType);
        changeRecord.setTransactionChannel(transactionChannel);
        changeRecord.setSourceOrderNo(crmGoodsOrder.getOrderNo());
        changeRecord.setOutAmount(orderAmount);
        changeRecord.setTransactionTime(LocalDateTime.now());
        changeRecordService.addRecord(changeRecord);
        /** 2.更新余额 */
        this.updateById(account);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void changeFromPaymentOrder(ExpensesPaymentOrder expensesPaymentOrder) {
        log.info("1.充值成功，处理支付订单");
        ExpensesAccount account = getByCompany(expensesPaymentOrder.getCompanyId());
        BigDecimal balance = account.getBalance();
        Integer paymentType = expensesPaymentOrder.getPaymentType();
        BigDecimal paymentAmount = expensesPaymentOrder.getPaymentAmount();
        /** 1.新增收支明细*/
        ExpensesBalanceChangeRecord changeRecord = new ExpensesBalanceChangeRecord();
        changeRecord.setTransactionType("Recharge");
        switch (paymentType){
            case 1: changeRecord.setTransactionChannel("WeChat");break;
            case 2: changeRecord.setTransactionChannel("AliPay");break;
        }
        changeRecord.setSourceOrderNo(expensesPaymentOrder.getOrderNo());
        changeRecord.setInAmount(paymentAmount);
        BigDecimal beforeChangeBalance = balance;
        BigDecimal afterChangeBalance = beforeChangeBalance.add(paymentAmount);
        changeRecord.setBeforeChangeBalance(beforeChangeBalance);
        changeRecord.setAfterChangeBalance(afterChangeBalance);
        changeRecord.setTransactionTime(LocalDateTime.now());
        changeRecordService.addRecord(changeRecord);
        /** 2.更新余额 */
        account.setBalance(afterChangeBalance);
        this.updateById(account);
        log.info("2.充值成功，处理支付订单，余额累加成功");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addDeposit(BigDecimal deposit) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        BigDecimal lowestDeposit = new BigDecimal(1000);
        ExpensesAccount expensesAccount = this.getByCompany(companyId);
        BigDecimal balance = expensesAccount.getBalance();
        BigDecimal myDeposit = expensesAccount.getDeposit();
        ExpensesBalanceChangeRecord changeRecord = new ExpensesBalanceChangeRecord();
        changeRecord.setCompanyId(companyId);
        String transactionType = "Deposit";
        String transactionChannel = "Balance";
        if(null == deposit){
            if( myDeposit.compareTo(lowestDeposit) >= 0) {
                throw new NuoNiuException("保证金余额充足");
            }
            deposit = lowestDeposit.subtract(myDeposit);
            if(balance.compareTo(deposit) < 0) {
                throw new  NuoNiuException("可用余额不足，请先充值");
            }
        }

        /** 减少 可用余额*/
        BigDecimal beforeChangeBalance = balance;
        BigDecimal afterChangeBalance = beforeChangeBalance.subtract(deposit);
        changeRecord.setBeforeChangeBalance(beforeChangeBalance);
        changeRecord.setAfterChangeBalance(afterChangeBalance);
        expensesAccount.setBalance(afterChangeBalance);
        /** 增加 保证金*/
        BigDecimal beforeChangeDeposit = myDeposit;
        BigDecimal afterChangeDeposit = beforeChangeDeposit.add(deposit);
        changeRecord.setBeforeChangeDeposit(beforeChangeDeposit);
        changeRecord.setAfterChangeDeposit(afterChangeDeposit);
        expensesAccount.setDeposit(afterChangeDeposit);

        changeRecord.setTransactionType(transactionType);
        changeRecord.setTransactionChannel(transactionChannel);
        changeRecord.setOutAmount(deposit);
        changeRecord.setTransactionTime(LocalDateTime.now());
        changeRecordService.addRecord(changeRecord);
        /** 2.更新余额 */
        this.updateById(expensesAccount);
        /** 校验外呼功能是否开启*/
        CrmCallMinutes callMinutes = crmCallMinutesService.checkByCompanyId(expensesAccount.getCompanyId());
        if(callMinutes.getStatus().equals(0)){
            crmCallMinutesService.openCallFunction(companyId);
        }
    }

    @Override
    public void deductionDeposit(Integer companyId, BigDecimal deposit) {
        if(null == deposit) {
            throw new NuoNiuException("扣除的保证金不能为空");
        }
        BigDecimal lowestDeposit = new BigDecimal(1000);
        ExpensesAccount expensesAccount = this.getByCompany(companyId);
        BigDecimal myDeposit = expensesAccount.getDeposit();
        ExpensesBalanceChangeRecord changeRecord = new ExpensesBalanceChangeRecord();
        String transactionType = "DeDeposit";
        String transactionChannel = "Deposit";
//        if( myDeposit.compareTo(deposit) > 0)throw new NuoNiuException("保证金不足(现有保证金："+ myDeposit +"元)，扣除失败");

        BigDecimal beforeChangeDeposit1 = myDeposit;
        BigDecimal afterChangeDeposit1 = beforeChangeDeposit1.subtract(deposit);
        changeRecord.setBeforeChangeDeposit(beforeChangeDeposit1);
        changeRecord.setAfterChangeDeposit(afterChangeDeposit1);
        expensesAccount.setDeposit(afterChangeDeposit1);

        changeRecord.setTransactionType(transactionType);
        changeRecord.setTransactionChannel(transactionChannel);
        changeRecord.setOutAmount(deposit);
        changeRecord.setTransactionTime(LocalDateTime.now());
        changeRecordService.addRecord(changeRecord);
        /** 2.更新余额 */
        this.updateById(expensesAccount);
        /** 如果小于最低保证金额度，则关闭外呼功能*/
        if(lowestDeposit.compareTo(expensesAccount.getDeposit()) >  0){
            crmCallMinutesService.closeCallFunction(companyId);
        }
    }


}
